{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ce5ac4f3-96f1-488d-b225-fb83fcd5591f",
   "metadata": {},
   "source": [
    "# 常用的两种归一化方法"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc587b6a-ee47-4699-a6a0-c801933282f9",
   "metadata": {},
   "source": [
    "## 一、零均值归一化（又叫标准化）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60193a6d-3734-431f-868a-6008257886e7",
   "metadata": {},
   "source": [
    "Z-Score Normalization"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b1f1adc-2ec8-445e-85a2-1e2b81476f39",
   "metadata": {},
   "source": [
    "标准化中的“标准”是指标准正态分布，标准正态分布的定义是均值为0，标准差为1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8bc4a6e4-daf5-49b9-8b1b-eaf88f220cf8",
   "metadata": {},
   "source": [
    "公式：\n",
    "$$\n",
    "Z = \\frac{X-\\mu}{\\sigma}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b1f67e10-d0a4-4c99-9f24-89a4f946d37d",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.neighbors import KNeighborsClassifier"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1df111da-1b91-496a-b4b5-4a90a47c4669",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "### 1、不做归一化的情况"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "a51bf45c-6a4d-49e3-ba20-4ff36ca847f2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>age</th>\n",
       "      <th>workclass</th>\n",
       "      <th>final_weight</th>\n",
       "      <th>education</th>\n",
       "      <th>education_num</th>\n",
       "      <th>marital_status</th>\n",
       "      <th>occupation</th>\n",
       "      <th>relationship</th>\n",
       "      <th>race</th>\n",
       "      <th>sex</th>\n",
       "      <th>capital_gain</th>\n",
       "      <th>capital_loss</th>\n",
       "      <th>hours_per_week</th>\n",
       "      <th>native_country</th>\n",
       "      <th>salary</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>39</td>\n",
       "      <td>State-gov</td>\n",
       "      <td>77516</td>\n",
       "      <td>Bachelors</td>\n",
       "      <td>13</td>\n",
       "      <td>Never-married</td>\n",
       "      <td>Adm-clerical</td>\n",
       "      <td>Not-in-family</td>\n",
       "      <td>White</td>\n",
       "      <td>Male</td>\n",
       "      <td>2174</td>\n",
       "      <td>0</td>\n",
       "      <td>40</td>\n",
       "      <td>United-States</td>\n",
       "      <td>&lt;=50K</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>50</td>\n",
       "      <td>Self-emp-not-inc</td>\n",
       "      <td>83311</td>\n",
       "      <td>Bachelors</td>\n",
       "      <td>13</td>\n",
       "      <td>Married-civ-spouse</td>\n",
       "      <td>Exec-managerial</td>\n",
       "      <td>Husband</td>\n",
       "      <td>White</td>\n",
       "      <td>Male</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>13</td>\n",
       "      <td>United-States</td>\n",
       "      <td>&lt;=50K</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>38</td>\n",
       "      <td>Private</td>\n",
       "      <td>215646</td>\n",
       "      <td>HS-grad</td>\n",
       "      <td>9</td>\n",
       "      <td>Divorced</td>\n",
       "      <td>Handlers-cleaners</td>\n",
       "      <td>Not-in-family</td>\n",
       "      <td>White</td>\n",
       "      <td>Male</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>40</td>\n",
       "      <td>United-States</td>\n",
       "      <td>&lt;=50K</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>53</td>\n",
       "      <td>Private</td>\n",
       "      <td>234721</td>\n",
       "      <td>11th</td>\n",
       "      <td>7</td>\n",
       "      <td>Married-civ-spouse</td>\n",
       "      <td>Handlers-cleaners</td>\n",
       "      <td>Husband</td>\n",
       "      <td>Black</td>\n",
       "      <td>Male</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>40</td>\n",
       "      <td>United-States</td>\n",
       "      <td>&lt;=50K</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>28</td>\n",
       "      <td>Private</td>\n",
       "      <td>338409</td>\n",
       "      <td>Bachelors</td>\n",
       "      <td>13</td>\n",
       "      <td>Married-civ-spouse</td>\n",
       "      <td>Prof-specialty</td>\n",
       "      <td>Wife</td>\n",
       "      <td>Black</td>\n",
       "      <td>Female</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>40</td>\n",
       "      <td>Cuba</td>\n",
       "      <td>&lt;=50K</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   age         workclass  final_weight  education  education_num  \\\n",
       "0   39         State-gov         77516  Bachelors             13   \n",
       "1   50  Self-emp-not-inc         83311  Bachelors             13   \n",
       "2   38           Private        215646    HS-grad              9   \n",
       "3   53           Private        234721       11th              7   \n",
       "4   28           Private        338409  Bachelors             13   \n",
       "\n",
       "       marital_status         occupation   relationship   race     sex  \\\n",
       "0       Never-married       Adm-clerical  Not-in-family  White    Male   \n",
       "1  Married-civ-spouse    Exec-managerial        Husband  White    Male   \n",
       "2            Divorced  Handlers-cleaners  Not-in-family  White    Male   \n",
       "3  Married-civ-spouse  Handlers-cleaners        Husband  Black    Male   \n",
       "4  Married-civ-spouse     Prof-specialty           Wife  Black  Female   \n",
       "\n",
       "   capital_gain  capital_loss  hours_per_week native_country salary  \n",
       "0          2174             0              40  United-States  <=50K  \n",
       "1             0             0              13  United-States  <=50K  \n",
       "2             0             0              40  United-States  <=50K  \n",
       "3             0             0              40  United-States  <=50K  \n",
       "4             0             0              40           Cuba  <=50K  "
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 以判断是否年薪50K的二分类项目为例\n",
    "data = pd.read_csv('adults.txt')\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "c6a8b2b8-da2b-422e-9098-7b9dc4a33cea",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 选取四个对年收入影响较大的特征（年龄、教育、职位、工作时长）\n",
    "feature = ['age', 'education', 'occupation', 'hours_per_week']\n",
    "target = data['salary'].values\n",
    "data = data[feature].copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "b6b0733c-82f5-4b87-aafb-78c450e69791",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>age</th>\n",
       "      <th>education</th>\n",
       "      <th>occupation</th>\n",
       "      <th>hours_per_week</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>39</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>50</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>13</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>38</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>53</td>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>28</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>32556</th>\n",
       "      <td>27</td>\n",
       "      <td>6</td>\n",
       "      <td>10</td>\n",
       "      <td>38</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>32557</th>\n",
       "      <td>40</td>\n",
       "      <td>1</td>\n",
       "      <td>9</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>32558</th>\n",
       "      <td>58</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>32559</th>\n",
       "      <td>22</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>20</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>32560</th>\n",
       "      <td>52</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>32561 rows × 4 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "       age  education  occupation  hours_per_week\n",
       "0       39          0           0              40\n",
       "1       50          0           1              13\n",
       "2       38          1           2              40\n",
       "3       53          2           2              40\n",
       "4       28          0           3              40\n",
       "...    ...        ...         ...             ...\n",
       "32556   27          6          10              38\n",
       "32557   40          1           9              40\n",
       "32558   58          1           0              40\n",
       "32559   22          1           0              20\n",
       "32560   52          1           1              40\n",
       "\n",
       "[32561 rows x 4 columns]"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 对类别型特征进行编码（因为这种特征是字符串object类型）\n",
    "for col in data.columns:\n",
    "    if data[col].dtype == 'object':\n",
    "        uni = data[col].unique()\n",
    "\n",
    "        def convert(item):\n",
    "            index = np.argwhere(uni == item)[0, 0]\n",
    "            return index\n",
    "\n",
    "        data[col] = data[col].map(convert)\n",
    "\n",
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "f93d5556-d6f0-42d2-8984-8b991174a747",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 划分数据集，固定随机数种子才好进行对比\n",
    "X_train, X_test, y_train, y_test = train_test_split(data.values, target, random_state=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "feb667dd-0314-4e16-9293-9c8349856d00",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7685787986733816"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 不做归一化直接训练并评估\n",
    "knn = KNeighborsClassifier()\n",
    "knn.fit(X_train, y_train)\n",
    "knn.score(X_test, y_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb362e6d-8b0a-4c7f-a01d-420d37e8a322",
   "metadata": {},
   "source": [
    "**不进行归一化：准确率=0.7685787986733816**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5c2fc58a-d162-42e5-9bfd-0d5697cb1b5f",
   "metadata": {},
   "source": [
    "### 2、进行零均值归一化（又叫标准化）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "32afe870-c61b-4714-b4eb-2032c9514a6e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>age</th>\n",
       "      <th>education</th>\n",
       "      <th>occupation</th>\n",
       "      <th>hours_per_week</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>39</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>50</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>13</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>38</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>53</td>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>28</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   age  education  occupation  hours_per_week\n",
       "0   39          0           0              40\n",
       "1   50          0           1              13\n",
       "2   38          1           2              40\n",
       "3   53          2           2              40\n",
       "4   28          0           3              40"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 查看一下data\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "4021dab5-7ea2-467e-9c60-828fbfd58a34",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用sklearn库中的StandardScaler\n",
    "from sklearn.preprocessing import StandardScaler"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "e3fdc8ee-1ea0-4ca6-b8dd-fb230049c566",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建一个标准化实例对象\n",
    "scaler = StandardScaler()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8abb7df-36ff-4409-b528-9a4d544e0e41",
   "metadata": {},
   "source": [
    "① 方法一：先fit再transform"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "2b145367-613d-4381-86a6-06d1880cf601",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-1 {color: black;}#sk-container-id-1 pre{padding: 0;}#sk-container-id-1 div.sk-toggleable {background-color: white;}#sk-container-id-1 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-1 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-1 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-1 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-1 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-1 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-1 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-1 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-1 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-1 div.sk-item {position: relative;z-index: 1;}#sk-container-id-1 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-1 div.sk-item::before, #sk-container-id-1 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-1 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-1 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-1 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-1 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-1 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-1 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-1 div.sk-label-container {text-align: center;}#sk-container-id-1 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-1 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>StandardScaler()</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" checked><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">StandardScaler</label><div class=\"sk-toggleable__content\"><pre>StandardScaler()</pre></div></div></div></div></div>"
      ],
      "text/plain": [
       "StandardScaler()"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "scaler.fit(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "729a1a4b-49c8-4885-afa7-3c9b65c60026",
   "metadata": {},
   "outputs": [],
   "source": [
    "data_scaled = scaler.transform(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "99bd7232-59c8-49b2-8f08-782b0d342170",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.03067056, -0.99158435, -1.37812112, -0.03542945],\n",
       "       [ 0.83710898, -0.99158435, -1.08279326, -2.22215312],\n",
       "       [-0.04264203, -0.70202542, -0.78746539, -0.03542945],\n",
       "       ...,\n",
       "       [ 1.42360965, -0.70202542, -1.37812112, -0.03542945],\n",
       "       [-1.21564337, -0.70202542, -1.37812112, -1.65522476],\n",
       "       [ 0.98373415, -0.70202542, -1.08279326, -0.03542945]])"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 此时的data_scaled就已经是经过标准化后的数据了\n",
    "data_scaled"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "87b8a4ca-3e32-4009-b138-a99f3528f46a",
   "metadata": {},
   "source": [
    "② 方法二：fit和transform一步到位"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "008e8247-5d81-4854-8b1e-d2eab1f3ae44",
   "metadata": {},
   "outputs": [],
   "source": [
    "scaler = StandardScaler()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "7eeb1916-780b-4852-b76d-4583472296cb",
   "metadata": {},
   "outputs": [],
   "source": [
    "data_scaled = scaler.fit_transform(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "0bc2f1e8-aceb-4dbf-87ab-c3319f11114d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-0.0"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 检查一下看看是不是均值为0\n",
    "round(data_scaled.mean(), 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "57475163-cc3d-4f0c-bccb-7c3bbdea5160",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 检查一下看看是不是标准差为1\n",
    "round(data_scaled.std(), 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "5e437459-b702-417d-955f-db382b419ec9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.773492199975433"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 划分数据集，进行模型训练和评估，使用相同的随机数种子\n",
    "X_train, X_test, y_train, y_test = train_test_split(data_scaled, target, random_state=0)\n",
    "knn = KNeighborsClassifier()\n",
    "knn.fit(X_train, y_train)\n",
    "knn.score(X_test, y_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "620634b3-1add-45dc-8485-e903f0b9bde2",
   "metadata": {},
   "source": [
    "**标准化后：准确率=0.773492199975433**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2540b3fd-71b5-407d-bc2e-414bb863f5c3",
   "metadata": {},
   "source": [
    "## 二、线性函数归一化（又叫Min-Max归一化）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "04a54067-aa91-45d9-9272-3a23121d0517",
   "metadata": {},
   "source": [
    "Min-Max Scaling"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fec9f5d0-b51d-4b32-bb48-0fde3eb65d4b",
   "metadata": {},
   "source": [
    "这是最常见的归一化形式，也被称为离差标准化，是把原始数据线性变换到 [0, 1] 区间。实现对数据的等比缩放。归一化公式如下：\n",
    "$$\n",
    "X_{norm} = \\frac{X-X_{min}}{X_{max}-X_{min}}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5760a9e5-b8f4-4100-b2cb-48c956ded42b",
   "metadata": {},
   "source": [
    "### 1、进行Min-Max归一化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "af440565-32cc-4adb-94ce-c81436b600b1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>age</th>\n",
       "      <th>education</th>\n",
       "      <th>occupation</th>\n",
       "      <th>hours_per_week</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>39</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>50</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>13</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>38</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>53</td>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>28</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   age  education  occupation  hours_per_week\n",
       "0   39          0           0              40\n",
       "1   50          0           1              13\n",
       "2   38          1           2              40\n",
       "3   53          2           2              40\n",
       "4   28          0           3              40"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 检查一下未归一化的数据\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "7e09dae6-5a80-4fb9-90c6-f2cdd9464bb0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 从sklearn的preprocessing中导入MinMaxScaler\n",
    "from sklearn.preprocessing import MinMaxScaler"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "9dcb2e4b-65d7-4625-9b29-f165b0c518c2",
   "metadata": {},
   "outputs": [],
   "source": [
    "scaler = MinMaxScaler()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "e405e26e-29f0-4303-b51f-3658f222501f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.30136986, 0.        , 0.        , 0.39795918],\n",
       "       [0.45205479, 0.        , 0.07142857, 0.12244898],\n",
       "       [0.28767123, 0.06666667, 0.14285714, 0.39795918],\n",
       "       ...,\n",
       "       [0.56164384, 0.06666667, 0.        , 0.39795918],\n",
       "       [0.06849315, 0.06666667, 0.        , 0.19387755],\n",
       "       [0.47945205, 0.06666667, 0.07142857, 0.39795918]])"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 生成归一化后的数据\n",
    "data_scaled = scaler.fit_transform(data)\n",
    "data_scaled"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "a919b0fb-cb66-4ab6-b0d5-737ea964f4f3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7801252917332023"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 划分数据集，进行模型训练和评估，使用相同的随机数种子\n",
    "X_train, X_test, y_train, y_test = train_test_split(data_scaled, target, random_state=0)\n",
    "knn = KNeighborsClassifier()\n",
    "knn.fit(X_train, y_train)\n",
    "knn.score(X_test, y_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00e0dbc3-2c9e-448a-bdd6-45ff36d08cab",
   "metadata": {},
   "source": [
    "**归一化：准确率=0.7801252917332023**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "04f725b2-d2d6-4035-ae39-16023a1e2f47",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
